//
//  Execute.swift
//  Network
//
//  Created by peiw on 2018/7/2.
//  Copyright © 2018年 Hiersun. All rights reserved.
//

import Foundation
import Moya
import SwiftyJSON
import ObjectMapper
import Alamofire

internal let reachability = Reachability()!

fileprivate func buildProvider<T: FxTargetType>(api: T) -> MoyaProvider<T> {
    let endpointClourse = { (target: T) -> Endpoint in
        let url = target.baseURL.appendingPathComponent(target.path, isDirectory: true).absoluteString
        let sampleResponseClosure = {() -> EndpointSampleResponse in
            return .networkResponse(200, target.sampleData)
        }
        let endpoint = Endpoint(url: url, sampleResponseClosure: sampleResponseClosure, method: target.method, task: target.task, httpHeaderFields: target.headers)
        return endpoint
    }
    let provider = MoyaProvider(endpointClosure: endpointClourse, stubClosure: api.useApiFixture ? MoyaProvider.immediatelyStub : MoyaProvider.neverStub)
    return provider
}

public extension FxTargetType {
    /// 执行网络请求并返回处理结果
    public func execute(completion: @escaping (_ result: FxResponseResult<JSON>) -> Void) {
        switch reachability.connection {
        case .none:
            requestPreviousHandler(.none)
        case .cellular:
            requestPreviousHandler(.wwan)
        case .wifi:
            requestPreviousHandler(.wifi)
        }
        
        buildProvider(api: self).request(self) { response in
            self.requestEndHandler(response.value)
            NetworkLog.printApi(api: self, msg: "has requested!")
            response
                .fxFlatMap { try? JSON(data: $0.data) }
                .map(self.responseHandler)
                .apply(completion)
        }
    }
    
    /// 执行网络请求并返回实体
    public func execute<T: Mappable>(completion: @escaping (_ result: FxResponseResult<T>) -> Void) {
        switch reachability.connection {
        case .none:
            requestPreviousHandler(.none)
        case .cellular:
            requestPreviousHandler(.wwan)
        case .wifi:
            requestPreviousHandler(.wifi)
        }
        buildProvider(api: self).request(self) { response in
            self.requestEndHandler(response.value)
            NetworkLog.printApi(api: self, msg: "has requested!")
            response
                .fxFlatMap { try? JSON(data: $0.data) }
                .map(self.responseHandler)
                .map { $0.dictionaryObject }
                .map { Mapper<T>().map(JSON: $0) }
                .apply(completion)
        }
    }
    
    /// 执行网络请求并返回实体数组
    public func execute<T: Mappable>(completion: @escaping (_ result: FxResponseResult<[T]>) -> Void) {
        switch reachability.connection {
        case .none:
            requestPreviousHandler(.none)
        case .cellular:
            requestPreviousHandler(.wwan)
        case .wifi:
            requestPreviousHandler(.wifi)
        }
        buildProvider(api: self).request(self) { response in
            self.requestEndHandler(response.value)
            NetworkLog.printApi(api: self, msg: "has requested!")
            response
                .fxFlatMap { try? JSON(data: $0.data) }
                .map(self.responseHandler)
                .map { $0.arrayObject as? [[String: Any]] }
                .map { Mapper<T>().mapArray(JSONArray: $0) }
                .apply(completion)
        }
    }
    
}
